package alarm

import (
	"errors"
	"fmt"
	"strconv"
	"sync"
	"time"

	"github.com/RuiGuangServer/config"
	"github.com/RuiGuangServer/global"
	"github.com/RuiGuangServer/logs"
)

func CheckLightingLevels(logger *logs.AsyncLogger) {
	now := time.Now().Unix()

	var wg sync.WaitGroup
	wg.Add(2)

	//限制等级
	mustLevel, err := levelForEtotEldt(now)
	if err != nil {
		handleServerError(logger)
		return
	} else {
		// 成功获取等级配置，清除服务器错误告警
		RemoveMessageItem("server_error", logger)
	}

	// 并行检查航班告警,起飞/落地前config.Config.LeadTime
	go func() {
		defer wg.Done()
		checkFlightAlerts(now, logger)
	}()

	// 3. 并行检查天气告警
	go func() {
		defer wg.Done()
		checkOtherAlerts(mustLevel, now, logger)
	}()

	wg.Wait()
}

func handleServerError(logger *logs.AsyncLogger) {
	if !isMessageTypeExists("server_error") {
		addMessageItem(&global.MessageItem{
			Typestr:   "server_error",
			WarnLevel: 2,
			Msgstr:    "服务器/数据故障",
			Kind:      1,
		}, logger)
	}
}

func isMessageTypeExists(typestr string) bool {
	_, exists := global.MsgItemCache.Load(typestr)
	return exists
}

func addMessageItem(item *global.MessageItem, logger *logs.AsyncLogger) {
	global.MsgItemCache.Store(item.Typestr, item)
	logger.Info("Added/Updated message item: %s", item.Typestr)
}

func RemoveMessageItem(typestr string, logger *logs.AsyncLogger) {
	exists := isMessageTypeExists(typestr)
	if exists {
		global.MsgItemCache.Delete(typestr)
		logger.Info("Removed message item: %s", typestr)
	}
}

func checkFlightAlerts(now int64, logger *logs.AsyncLogger) {
	global.PlanMap.Range(func(key, value any) bool {
		callsign := key.(string)
		plan := value.(*global.PlanState)

		var eventTime int64
		var eventType string
		var alertKey string

		if plan.DES == config.Config.AirPort {
			eventTime = plan.Aldt // 降落时间
			eventType = "落地"
			alertKey = "landing_" + callsign
		} else if plan.DEP == config.Config.AirPort {
			eventTime = plan.Etot // 起飞时间
			eventType = "起飞"
			alertKey = "takeoff_" + callsign
		} else {
			return true // 继续迭代
		}
		leadTime := int64(config.Config.LeadTime)
		leadTimes := int64(leadTime / 60)

		// 检查是否在30分钟窗口内
		if eventTime > now && eventTime-now <= leadTime {
			// fmt.Printf("alarm plan:%v\n", plan)
			levels, err := levelForEtotEldt(eventTime)
			if err != nil {
				logger.Warn("Failed to get levels for %s: %v", callsign, err)
				return true // 继续迭代
			}

			hasInsufficient := false
			hasExcessive := false
			adviseKey := "advise_" + callsign

			// 处理等级过高情况
			recommendedLevels := make([]string, 0)

			for lightKey, requiredLevel := range levels {
				currentLevel, ok := getCurrentLightLevel(lightKey)
				if !ok {
					hasInsufficient = true
					break
				}
				if currentLevel < requiredLevel {
					hasInsufficient = true
					break
				} else if currentLevel > requiredLevel {
					hasExcessive = true
					// 记录建议等级
					lightName := getLightName(lightKey)
					recommendedLevels = append(recommendedLevels, fmt.Sprintf("%s%d级", lightName, requiredLevel))
				}
			}

			if hasInsufficient {
				if !isMessageTypeExists(alertKey) {
					addMessageItem(&global.MessageItem{
						Typestr:   alertKey,
						WarnLevel: 1,
						Msgstr:    fmt.Sprintf("距离%s%s前%d分钟，请开启所需助航灯光", callsign, eventType, leadTimes),
						Kind:      2, // 航班计划开灯告警
					}, logger)
					// 移除对应的建议
					RemoveMessageItem(adviseKey, logger)
					RemoveMessageItem("advise", logger)
				}
			} else if hasExcessive {
				if !isMessageTypeExists(adviseKey) {
					// 构建建议消息
					recommendationMsg := "当前助航灯光等级过高，建议调低至:"
					for _, rec := range recommendedLevels {
						recommendationMsg += rec + " "
					}
					recommendationMsg += "以节约能源"

					addMessageItem(&global.MessageItem{
						Typestr:   adviseKey,
						WarnLevel: 3,
						Msgstr:    fmt.Sprintf("距离%s%s前%d分钟，%s", callsign, eventType, leadTimes, recommendationMsg),
						Kind:      1, // 其它告警建议
					}, logger)
					// 移除对应的告警
					RemoveMessageItem(alertKey, logger)
					RemoveMessageItem("advise", logger)
				}
			} else {
				// 等级合适，移除告警和建议
				RemoveMessageItem(alertKey, logger)
				RemoveMessageItem(adviseKey, logger)
			}
		}
		plan.Stime = now
		return true // 继续迭代
	})
}

func checkOtherAlerts(mustLevel map[string]int, now int64, logger *logs.AsyncLogger) {
	// 检查一段时间内是否有航班
	hasFlightInTime := hasFlightWithinMinutes(now)
	// 有航班时，移除没有航班时的建议
	if hasFlightInTime {
		RemoveMessageItem("advise", logger)
	} else {
		// 一段时间内没有航班，移除日出日落和灯光一致性告警
		RemoveMessageItem("sunrise", logger)
		RemoveMessageItem("sunset", logger)
		RemoveMessageItem("consistency", logger)
		RemoveMessageItem("weather", logger)
		RemoveMessageItem("level_too_high", logger)
		if !isMessageTypeExists("advise") {
			addMessageItem(&global.MessageItem{
				Typestr:   "advise",
				WarnLevel: 3,
				Msgstr:    "当前没有航班，可以关闭助航灯光",
				Kind:      1, // 其它告警建议
			}, logger)
		}
		return
	}

	// 检查灯光等级是否合适
	hasInsufficient := false
	hasExcessive := false
	// 处理等级过高情况
	recommendedLevels := make([]string, 0)

	for lightKey, requiredLevel := range mustLevel {
		currentLevel, ok := getCurrentLightLevel(lightKey)
		if !ok {
			hasInsufficient = true
			break
		}
		if currentLevel < requiredLevel {
			hasInsufficient = true
			break
		} else if currentLevel > requiredLevel {
			hasExcessive = true
			// 记录建议等级
			lightName := getLightName(lightKey)
			recommendedLevels = append(recommendedLevels, fmt.Sprintf("%s%d级", lightName, requiredLevel))
		}
	}

	if hasInsufficient {
		// 等级不足，检查具体原因
		state, ok := global.CurrentAirPortState.Load(config.Config.AirPort)
		if !ok {
			logger.Error("waiting for AWOS and Weather interface to return data")
			return
		}
		currentState := state.(*global.AirPortState)
		if currentState.Oper == 1 && !isMessageTypeExists("weather") {
			addMessageItem(&global.MessageItem{
				Typestr:   "weather",
				WarnLevel: 1,
				Msgstr:    "RVR/能见度/云高有变化，注意调整助航灯光",
				Kind:      0, // 气象信息变化调级告警
			}, logger)
			currentState.Oper = 0
			// 移除等级过高建议
			RemoveMessageItem("level_too_high", logger)
			return
		}

		sunrise, sunset, err := config.GetSuntime()
		if err != nil {
			logger.Warn("Alarm error:%v", err)
			return
		}

		isSunriseTwilight := now >= (sunrise-30*60) && now < sunrise
		isSunsetTwilight := now >= sunset && now < (sunset+30*60)
		isTwilight := isSunriseTwilight || isSunsetTwilight

		// 只有在60分钟内有航班的情况下才检查日出日落和灯光一致性告警
		if hasFlightInTime {
			if !isTwilight && !isMessageTypeExists("consistency") {
				addMessageItem(&global.MessageItem{
					Typestr:   "consistency",
					WarnLevel: 2,
					Msgstr:    "灯光开启错误，请检查",
					Kind:      1, // 其它告警建议
				}, logger)
				RemoveMessageItem("sunrise", logger)
				RemoveMessageItem("sunset", logger)
				// 移除等级过高建议
				RemoveMessageItem("level_too_high", logger)
				return
			}
			if isSunriseTwilight && !isMessageTypeExists("sunrise") {
				addMessageItem(&global.MessageItem{
					Typestr:   "sunrise",
					WarnLevel: 2,
					Msgstr:    "日出前30分钟，请开启所需助航灯光",
					Kind:      1, // 其它告警建议
				}, logger)
				RemoveMessageItem("consistency", logger)
				// 移除等级过高建议
				RemoveMessageItem("level_too_high", logger)
				return
			}
			if isSunsetTwilight && !isMessageTypeExists("sunset") {
				addMessageItem(&global.MessageItem{
					Typestr:   "sunset",
					WarnLevel: 2,
					Msgstr:    "日落前30分钟，请开启所需助航灯光",
					Kind:      1, // 其它告警建议
				}, logger)
				RemoveMessageItem("consistency", logger)
				// 移除等级过高建议
				RemoveMessageItem("level_too_high", logger)
				return
			}
		}
	} else if hasExcessive {
		// 等级过高，给出建议
		if !isMessageTypeExists("level_too_high") {
			// 构建建议消息
			recommendationMsg := "当前助航灯光等级过高，建议调低至:"
			for _, rec := range recommendedLevels {
				recommendationMsg += rec + " "
			}
			recommendationMsg += "以节约能源"

			addMessageItem(&global.MessageItem{
				Typestr:   "level_too_high",
				WarnLevel: 3,
				Msgstr:    recommendationMsg,
				Kind:      1, // 其它告警建议
			}, logger)
		}
		// 移除其它告警
		RemoveMessageItem("weather", logger)
		RemoveMessageItem("consistency", logger)
		RemoveMessageItem("sunrise", logger)
		RemoveMessageItem("sunset", logger)
	} else {
		// 等级合适，移除所有告警和建议
		RemoveMessageItem("weather", logger)
		RemoveMessageItem("consistency", logger)
		RemoveMessageItem("sunrise", logger)
		RemoveMessageItem("sunset", logger)
		RemoveMessageItem("level_too_high", logger)
	}
}

// 当前一段时间内是否有航班起飞落地
func hasFlightWithinMinutes(now int64) bool {
	hasFlight := false
	sixtyMinutes := int64(config.Config.LastTime)
	global.PlanMap.Range(func(key, value any) bool {
		plan := value.(*global.PlanState)

		// 检查起飞或降落时间是否在未来时间内
		if (plan.DEP == config.Config.AirPort && plan.Etot > now && plan.Etot <= now+sixtyMinutes) ||
			(plan.DES == config.Config.AirPort && plan.Aldt > now && plan.Aldt <= now+sixtyMinutes) {
			hasFlight = true
			return false // 找到符合条件的航班，停止迭代
		}
		return true // 继续迭代
	})

	return hasFlight
}

// 辅助函数：获取灯光的当前等级
func getCurrentLightLevel(lightKey string) (int, bool) {
	data, _ := global.LightData.Load().(map[string]*global.Listlight)

	for _, light := range data {
		if light.Key == lightKey {
			level, err := strconv.Atoi(light.Value)
			if err != nil {
				return 0, false
			}
			return level, true
		}
	}
	return 0, false
}

// 获取灯光名称
func getLightName(lightKey string) string {
	// 这里可以根据lightKey返回对应的灯光名称
	// 例如，如果lightKey是"PabiLight"，返回"进近坡度灯"
	// 实际实现可能需要从配置中获取映射关系
	switch lightKey {
	case "ApproachLight":
		return "进近灯"
	case "PabiLight":
		return "进近坡度灯"
	case "EdgeLight":
		return "跑道边灯"
	case "CenterLight":
		return "跑道中心线灯"
	default:
		return lightKey
	}
}

// 根据起飞/降落时间得到有效的灯光等级
func levelForEtotEldt(times int64) (map[string]int, error) {
	lightLevel := make(map[string]int)

	// 获取当前机场状态
	state, ok := global.CurrentAirPortState.Load(config.Config.AirPort)
	if !ok {
		return nil, errors.New("waiting for AWOS and Weather interface to return data")
	}
	currentState := state.(*global.AirPortState)

	// 获取能见度值（考虑不同场景）
	visibility := getVisibilityValue(currentState)
	// fmt.Printf("alarm LightConfig:%v\n", global.LightConfig)

	for _, lights := range global.LightConfig {
		class := getLightClass(lights.Type)
		clockType, err := config.GetClockType(times, class)
		if err != nil {
			return nil, err
		}
		requiredLevel := findRequiredLevel(lights.LevelInfo, clockType, visibility, currentState)
		lightLevel[lights.Key] = requiredLevel
	}

	if len(lightLevel) == 0 {
		return nil, fmt.Errorf("未找到任何匹配的灯光配置")
	}

	return lightLevel, nil
}

// 获取有效的能见度值
func getVisibilityValue(state *global.AirPortState) int64 {
	// RVR≤2000时使用自观能见度(Vis1A)
	if state.Rvr <= 2000 && state.Vis1A > 0 {
		return state.Vis1A
	}

	// 否则使用气象能见度(Vis)
	if state.Vis > 0 {
		return state.Vis
	}

	return -1
}

// 获取灯光类型对应的class
func getLightClass(lightType int) int {
	switch lightType {
	case 2: // PabiLight
		return 1
	case 3: // EdgeLight
		return 2
	default:
		return 0
	}
}

// 查找所需的灯光等级
func findRequiredLevel(lightConfig []global.ClockLevel, clockType int, visibility int64, state *global.AirPortState) int {
	for _, cl := range lightConfig {
		if cl.Clock != clockType {
			continue
		}

		// 云高≤300时强制使用最大等级
		if state.Cloud <= 300 {
			return cl.MaxLevel
		}

		for _, vl := range cl.VL {
			if visibility > int64(vl.MinVis) && visibility <= int64(vl.MaxVis) {
				return vl.Level
			}
		}
	}
	return 0
}
